/**
 * FileName:   AppUtil.java
 * Description:
 * 项目常用工具
 * History:
 * Version    Author       Date        Introduce
 * 1.0        xxb        2018-05       New
 */

package com.csun.cmny.provider.utils;

import org.apache.commons.codec.digest.DigestUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.math.BigDecimal;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public final class AppUtil {

    /**
     * 日志文件
     */
    private static final Logger LOGGER = LoggerFactory.getLogger(AppUtil.class);

    /**
     * 生成随机字符集合
     */
    private static final String ALLCHAR = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";

    /**
     * 所有数字
     */
    private static final String ALL_NUMBER= "0123456789";

    /**
     * 随机字符串长度8位
     */
    private static final int NOTE_LENGHT = 8;

    /**
     * 数组字符串
     */
    private static final String REG_NUMBER = "^[0-9]*$";

    /**
     * 标准格式yyyy-MM-dd HH:mm:ss
     */
    public static final String YYYY_MM_DD_HH_MM_SS = "yyyy-MM-dd HH:mm:ss";

    /**
     * 短时间类型
     */
    public static final String YYYY_MM_DD = "yyyy-MM-dd";

    /**
     * 短时间类型
     */
    public static final String YYYYMM = "yyyyMM";

    /**
     * 紧凑长时间格式yyyyMMddHHmmss
     */
    public static final String YYYYMMDDHHMMSS = "yyyyMMddHHmmss";

    /**
     * 紧凑长时间格式yyyyMMddHHmmss
     */
    public static final String YYYYMMDDHHMMSS_SS = "yyyyMMddHHmmssSS";

    /**
     * TIMEZONE
     */
    public static final String TIMEZONE = "GMT+8";

    /**
     * 默认页号
     */
    private static final int DEFAULT_PAGE = 1;

    /**
     * 默认页记录数
     */
    private static final int DEFAULT_PAGESIZE = 20;

    /**
     * Empty String
     */
    private static final String STRING_EMPTY = "";

    /**
     * Sql危险字符
     */
    private static final String[] BADSQLWORD = {" ", "'", "\"", ";", "@", "|", "\\?", "\\*", "#", "/", "\\\\", ",", "=", "-", "%", "union", "or", "like"};

    /**
     * BigDecimal 格式化
     *
     * @param input
     * @return
     */
    public static String formatDecimal(BigDecimal input) {
        return null == input ? "0.00" : new java.text.DecimalFormat("#0.00").format(input);
    }

    /**
     * 格式化日期
     *
     * @param date       日期对象
     * @param strPattern 格式表达式
     * @return 日期字符串
     */
    public static String formatDate(Date date, String strPattern) {
        SimpleDateFormat df = new SimpleDateFormat(strPattern);
        df.setTimeZone(TimeZone.getTimeZone(TIMEZONE));
        return df.format(date);
    }

    /**
     * 格式化日期，默认YYYY-MM-dd HH:mm:ss
     *
     * @param date 日期对象
     * @return 日期字符串
     */
    public static String formatDate(Date date) {
        if(null == date){
            return null;
        }
        SimpleDateFormat df = new SimpleDateFormat(YYYY_MM_DD_HH_MM_SS);
        df.setTimeZone(TimeZone.getTimeZone(TIMEZONE));
        return df.format(date);
    }


    /**
     * 字符串是否为空
     *
     * @param inputStr 待检查字符串
     * @return 字符串是否为空
     */
    public static boolean isNullOrEmpty(String inputStr) {
        return (null == inputStr || "".equals(inputStr.trim()));
    }

    /**
     * 数字是否为空或是为0
     *
     * @param inputNumber
     * @return
     */
    public static boolean numIsNullOrZero(Integer inputNumber) {
        return (null == inputNumber || inputNumber == 0);
    }

    /**
     * 格式化Double数,保留2位小数
     *
     * @param inputDouble 要格式化的数
     * @return
     */
    public static String formatDoubleWithScaleTwo(Double inputDouble) {
        return doubleIsNull(inputDouble) ? "0.00" : String.format("%.2f", inputDouble);
    }

    /**
     * Double数字是否为空
     *
     * @param dInput
     * @return
     */
    public static boolean doubleIsNull(Double dInput) {
        return null == dInput;
    }

    /**
     * 默认生成8位随机字符串
     *
     * @return
     */
    public static String generateString() {
        final StringBuilder sb = new StringBuilder(NOTE_LENGHT);
        final Random random = new Random();
        for (int i = 0; i < NOTE_LENGHT; i++) {
            sb.append(ALLCHAR.charAt(random.nextInt(ALLCHAR.length() - 1)));
        }
        return sb.toString();
    }
    
    /**
     * 生成随机数
     * @param length 随机数长度
     * @return
     */
    public static String generateNum(int length) {
        final StringBuilder sb = new StringBuilder(length);
        final Random random = new Random();
        for (int i = 0; i < length; i++) {
            sb.append(random.nextInt(10));
        }
        return sb.toString();
    }
    
    /**
     * apache.commons.codec  md5Hex算法
     *
     * @param strInput 字符串
     * @return 大写MD5
     */
    public static String md5Hex(String strInput) {
        if (isNullOrEmpty(strInput)) {
            return "";
        }
        return DigestUtils.md5Hex(strInput).toLowerCase();
    }

    /**
     * 验证数组字符串有效性
     *
     * @param strNumber
     * @return
     */
    public static boolean regNumber(String strNumber) {
        Pattern p = Pattern.compile(REG_NUMBER);
        Matcher m = p.matcher(strNumber);
        return m.matches();
    }

    /**
     * 不全为数字字符串
     *
     * @param strNumber
     * @return
     */
    public static boolean regNotNumber(String strNumber) {
        return !regNumber(strNumber);
    }

    /**
     * 验证字符串长度
     *
     * @param strInput 输入字符串
     * @param nLen     长度
     * @return
     */
    public static boolean isLen(String strInput, int nLen) {
        if (null == strInput) {
            return false;
        }
        return strInput.length() == nLen;
    }

    /**
     * 是否为未来的时间
     *
     * @param strDate
     * @return
     */
    public static boolean isAfterNow(String strDate) {
        boolean bRe = false;
        try {
            Date dtNow = new Date();
            Date dt = parseDate(strDate, YYYY_MM_DD_HH_MM_SS);
            return dtNow.before(dt);
        } catch (Exception ex) {
            LOGGER.error("日期比较发生错误:" + ex.toString());
        }

        return bRe;
    }


    /**
     * 字符串日期时间转换日期
     *
     * @param strDate    日期字符串
     * @param strPattern 格式
     * @return 是否为正确的日期时间格式
     */
    public static boolean checkDateFormat(String strDate, String strPattern) {
        if (isNullOrEmpty(strDate)) {
            return false;
        }

        SimpleDateFormat df = new SimpleDateFormat(strPattern);
        df.setTimeZone(TimeZone.getTimeZone(TIMEZONE));
        try {
            df.parse(strDate);
            return true;
        } catch (ParseException e) {
            return false;
        }
    }

    /**
     * 转换日期为yyyyMMddHHmmss紧凑字符串格式
     *
     * @param dt
     * @return
     */
    public static String compactDateFormat(Date dt) {
        if (null == dt) {
            return null;
        }

        SimpleDateFormat df = new SimpleDateFormat(YYYYMMDDHHMMSS);
        df.setTimeZone(TimeZone.getTimeZone(TIMEZONE));
        try {
            return df.format(dt);
        } catch (Exception e) {
            return null;
        }
    }

    /**
     * 当前时间戳的字符串形式
     *
     * @return
     */
    public static String strTimestamp() {
        return String.valueOf(System.currentTimeMillis());
    }

    /**
     * 当前时间戳毫秒
     *
     * @return
     */
    public static Long timestamp() {
        return System.currentTimeMillis();
    }

    /**
     * 格式化的字符串转化为日期时间
     *
     * @param dateFormat
     * @return
     */
    public static Date str2Date(String dateFormat) {
        Date date = null;
        try {
            date = parseDate(dateFormat, YYYY_MM_DD_HH_MM_SS);
        } catch (ParseException e) {
            LOGGER.error(e.toString());
        }
        return date;
    }

    /**
     * 字符串日期时间转换日期
     *
     * @param strDate    日期字符串
     * @param strPattern 格式表达式
     * @return 日期对象
     */
    public static Date parseDate(String strDate, String strPattern) throws ParseException {
        SimpleDateFormat df = new SimpleDateFormat(strPattern);
        df.setTimeZone(TimeZone.getTimeZone(TIMEZONE));
        return df.parse(strDate);
    }

    /**
     * 字符串日期时间转换日期
     *
     * @param strDate 日期字符串
     * @return 日期对象
     */
    public static Date parseDate(String strDate) {
        SimpleDateFormat df = new SimpleDateFormat(YYYYMMDDHHMMSS);
        df.setTimeZone(TimeZone.getTimeZone(TIMEZONE));
        try {
            return df.parse(strDate);
        } catch (ParseException e) {
            throw new IllegalArgumentException(e);
        }
    }

    /**
     * 字符串为空返回默认字符串
     *
     * @param strInput
     * @param strDef
     * @return
     */
    public static String getDefaultStr(String strInput, String strDef) {
        return null == strInput ? strDef : strInput;
    }

    /**
     * 字符串为空返回""字符串
     *
     * @param strInput
     * @return
     */
    public static String getDefaultStr(String strInput) {
        return null == strInput ? "" : strInput;
    }

    /**
     * 分页页号，默认第一页
     *
     * @param obj
     * @return
     */
    public static int getPage(Object obj) {
        if (null == obj) {
            return DEFAULT_PAGE;
        }

        try {
            return Integer.valueOf(String.valueOf(obj));
        } catch (Exception ex) {
            return DEFAULT_PAGE;
        }
    }

    /**
     * 分页页号，默认第一页
     *
     * @param nPage
     * @return
     */
    public static int getPage(Integer nPage) {
        return null == nPage ? DEFAULT_PAGE : nPage;
    }

    /**
     * 分页每页记录数，默认20条记录
     *
     * @param nPageSize
     * @return
     */
    public static int getPageSize(Integer nPageSize) {
        return null == nPageSize ? DEFAULT_PAGESIZE : nPageSize;
    }

    /**
     * 分页每页记录数，默认20条记录
     *
     * @param obj
     * @return
     */
    public static int getPageSize(Object obj) {
        if (null == obj) {
            return DEFAULT_PAGESIZE;
        }

        try {
            return Integer.valueOf(String.valueOf(obj));
        } catch (Exception ex) {
            return DEFAULT_PAGESIZE;
        }
    }

    /**
     * 过滤sql危险字符串后拼接查询
     *
     * @param obj
     * @return
     */
    public static String getSqlLike(Object obj) {
        return "%" + AppUtil.sqlFilter(String.valueOf(obj)) + "%";
    }

    /**
     * 过滤sql危险字符
     *
     * @param strInput
     * @return
     */
    public static String sqlFilter(String strInput) {
        if (null == strInput || strInput.length() == 0) {
            return STRING_EMPTY;
        }

        String strRe = strInput;
        for (String badword : BADSQLWORD) {
            strRe = replaceNoCase(strRe, badword, STRING_EMPTY);
        }

        return strRe;
    }

    /**
     * 不区分大小写替换字符串
     *
     * @return
     */
    public static String replaceNoCase(String strInput,
                                       String strOld, String strNew) {
        if (null == strInput || strInput.length() == 0) {
            return STRING_EMPTY;
        }
        Pattern p = Pattern.compile(strOld, Pattern.CASE_INSENSITIVE);
        Matcher m = p.matcher(strInput);
        return m.replaceAll(strNew);
    }

    /**
     * 对向的字符串值
     *
     * @param obj
     * @return
     */
    public static String getStrVale(Object obj) {
        return null == obj ? STRING_EMPTY : String.valueOf(obj);
    }

    /**
     * 开始日期处理
     * 不正确返回当前日期
     *
     * @param obj
     * @return
     */
    public static String getBeginDate(Object obj) {
        if (null == obj || !isDateTime((String) obj, YYYY_MM_DD)) {
            return formatDate(new Date(), YYYY_MM_DD) + " 00:00:00";
        }
        return (String) obj + " 00:00:00";
    }

    /**
     * 开始日期处理
     * 不正确返回当前日期
     *
     * @param obj
     * @return
     */
    public static String getBeginDateShort(Object obj) {
        if (null == obj || !isDateTime((String) obj, YYYY_MM_DD)) {
            return formatDate(new Date(), YYYY_MM_DD);
        }
        return (String) obj;
    }

    /**
     * 结束日期处理
     * 不正确返回当前日期
     *
     * @param obj
     * @return
     */
    public static String getEndDateShort(Object obj) {
        if (null == obj || !isDateTime((String) obj, YYYY_MM_DD)) {
            return formatDate(new Date(), YYYY_MM_DD);
        }
        return (String) obj;
    }

    /**
     * 结束日期处理
     * 不正确返回当前日期
     *
     * @param obj
     * @return
     */
    public static String getEndDate(Object obj) {
        if (null == obj || !isDateTime((String) obj, YYYY_MM_DD)) {
            return formatDate(new Date(), YYYY_MM_DD) + " 23:59:59";
        }
        return String.valueOf(obj) + " 23:59:59";
    }

    /**
     * 是否为日期时间格式
     *
     * @param strDateTime
     * @param pattern
     * @return
     */
    public static boolean isDateTime(String strDateTime, String pattern) {
        boolean bRe = false;
        DateFormat dateFormat = new SimpleDateFormat(pattern);
        try {
            dateFormat.parse(strDateTime);
            bRe = true;
        } catch (Exception ex) {
            bRe = false;
        }
        return bRe;
    }

    /**
     * Uuid字符串，过滤"-"
     *
     * @return
     */
    public static String generateUuid() {
        return UUID.randomUUID().toString().replaceAll("-", "");
    }

    public static Date getTodayBegin() {
        Date now = new Date();
        Calendar cl = Calendar.getInstance();
        cl.setTime(now);
        cl.set(Calendar.HOUR_OF_DAY, 0);
        cl.set(Calendar.MINUTE, 0);
        cl.set(Calendar.SECOND, 0);
        cl.set(Calendar.MILLISECOND, 0);
        return cl.getTime();
    }

    public static Date getTodayEnd() {
        Date now = new Date();
        Calendar cl = Calendar.getInstance();
        cl.setTime(now);
        cl.set(Calendar.HOUR_OF_DAY, 23);
        cl.set(Calendar.MINUTE, 59);
        cl.set(Calendar.SECOND, 59);
        cl.set(Calendar.MILLISECOND, 999);
        return cl.getTime();
    }


    /**
     * 过滤字符串换行符、\t,\n,\r,空格
     * @param str
     * @return
     */
    public static String filterStr(String str){
        return  str.replaceAll("\t|\n|\r","").replaceAll(" ","");
    }

}
